/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: SunlordServiceImpl
 * Author:   Administrator
 * Date:     2019/6/10 15:53
 * Description: 商洛service 实现
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.sunlord.service.impl;

import OThinker.Common.Data.Database.ICommand;
import OThinker.Common.Organization.Models.User;
import OThinker.H3.Entity.Data.DataLogicType;
import OThinker.H3.Entity.DataModel.BizObject;
import OThinker.H3.Entity.DataModel.BizObjectSchema;
import OThinker.H3.Entity.DataModel.PropertySchema;
import OThinker.H3.Entity.Instance.Data.InstanceData;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.h3bpm.base.util.AppUtility;
import com.sunlord.dto.BpcMaster;
import com.sunlord.dto.CustFilingX3Data;
import com.sunlord.dto.SunlordResult;
import com.sunlord.service.SunlordService;
import com.sunlord.utils.DbConfigUtil;
import com.sunlord.utils.TableKeyWord;
import oracle.sql.DATE;
import oracle.sql.NUMBER;
import oracle.sql.TIMESTAMP;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.sql.*;
import java.util.*;

/**
 * 〈一句话功能简述〉<br>
 * 〈商洛service 实现〉
 *
 * @author Administrator
 * @create 2019/6/10
 * @since 1.0.0
 */
@Service
public class SunlordServiceImpl implements SunlordService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SunlordServiceImpl.class);

    @Override
    public boolean custFilingSaveToX3(CustFilingX3Data cfxd) {

        if(cfxd == null) {
            return  false;
        }
        Connection conn = null;
        //X3主数据
        PreparedStatement saveZbpCustomerPs = null;
         //客户地址
        PreparedStatement saveZbpAddressPs = null;
        //收获地址
        PreparedStatement saveZbpdlvcustPs = null;
        //联系人
        PreparedStatement saveContactPs = null;

        // 是否成功
        boolean result = false;
        Object[] colArray ;
        JSONObject colMapping;
        try {
            // 回写
            conn = DbConfigUtil.getConn("oracle.jdbc.OracleDriver", "SUNLORD");
            conn.setAutoCommit(false);

            //主数据
            colMapping = JSON.parseObject(CustFilingX3Data.getZbpCustomerSaveCol());
            colArray =  colMapping.keySet().toArray();
            saveZbpCustomerPs =  conn.prepareStatement(this.crateInsertSql(colArray, CustFilingX3Data.getZbpCustomerTableName()));
            this.psSetParam(saveZbpCustomerPs,cfxd.getBpCustomerData(),colArray,colMapping);
            saveZbpCustomerPs.execute();

            //客户地址
            if (!cfxd.getBpAddressDataList().isEmpty()){
                colMapping = JSON.parseObject(CustFilingX3Data.getZbpAddressSaveCol());
                colArray =  colMapping.keySet().toArray();
                saveZbpAddressPs =  conn.prepareStatement(this.crateInsertSql(colArray, CustFilingX3Data.getZbpAddressTableName()));
                executeSql(saveZbpAddressPs,cfxd.getBpAddressDataList(),colArray,colMapping);
            }

            //收货地址
            if (!cfxd.getBpDlvcustDataList().isEmpty()){
                colMapping = JSON.parseObject(CustFilingX3Data.getBpdlvcustSaveCol());
                colArray =  colMapping.keySet().toArray();
                saveZbpdlvcustPs =  conn.prepareStatement(this.crateInsertSql(colArray, CustFilingX3Data.getBpdlvcustTableName()));
                executeSql(saveZbpdlvcustPs,cfxd.getBpDlvcustDataList(),colArray,colMapping);
            }


            //联系人地址
            if(!cfxd.getContactDataList().isEmpty()){
                colMapping = JSON.parseObject(CustFilingX3Data.getContactSaveCol());
                colArray =  colMapping.keySet().toArray();
                saveContactPs =  conn.prepareStatement(this.crateInsertSql(colArray, CustFilingX3Data.getContactTableName()));
                executeSql(saveContactPs,cfxd.getContactDataList(),colArray,colMapping);
            }

            conn.commit();
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.warn(e.getMessage());
            try {
                conn.rollback();
            } catch (SQLException sqle) {
                LOGGER.warn(sqle.getMessage());
            }
        }finally {
            ArrayList<PreparedStatement> pslist = new ArrayList<>();
            pslist.add(saveZbpCustomerPs);
            pslist.add(saveZbpAddressPs);
            pslist.add(saveZbpdlvcustPs);
            pslist.add(saveContactPs);
            closeConnection(null,pslist,conn);
        }

        return result;
    }



    @Override
    public boolean custModify(InstanceData sourceData, InstanceData destData,Map<String,String> destSourceFeild)  {
        try {
            if (sourceData == null ){
                LOGGER.info("建档变更: 源实例数据为 null,instanceId:"+sourceData.getInstanceId());
                return  false;
            }
            if (sourceData == null ){
                LOGGER.info("建档变更: 目标实例数据为 null,instanceId:"+destData.getInstanceId());
                return  false;
            }

            copyBizObjectToBizObject(sourceData,destData,destSourceFeild);

            destData.Submit();

        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.info("建档变更异常:"+e.getMessage());
            return  false;
        }

        return true;
    }

    @Override
    public SunlordResult x3fanxie(String x3Sql,String key,String... value) {
        PreparedStatement  ps  = null;
        Connection conn = null;
        ResultSet rs = null;
        try {

            conn = DbConfigUtil.getConn("oracle.jdbc.OracleDriver", "SUNLORD");

            ps = conn.prepareStatement(x3Sql);
            rs = ps.executeQuery();
            Map<String, List<Object>> map = new HashMap<>(32);
            List<Object> valueList;
            while(rs.next()){
                valueList = new ArrayList<>(value.length);
                for (int i = 0; i < value.length; i++) {
                    valueList.add(rs.getObject(value[i]));
                }
                map.put(rs.getString(key),valueList);
            }

            return SunlordResult.success(map);

        } catch (Exception e) {

            LOGGER.info(e.getMessage(),e);
            return SunlordResult.fail("系统异常");
        }finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception e) {
                LOGGER.warn(e.getMessage());
            }

        }
    }

    @Override
    public boolean ExecuteEngineSql( List<String> sqlList){
        boolean flag = false;


        Connection conn = null;
        //X3主数据
        Statement stmt = null;
        ArrayList<Statement> pslist = new ArrayList<>();

        try {
            // 回写
            conn = DbConfigUtil.getConn("oracle.jdbc.OracleDriver", "Engine");
            conn.setAutoCommit(false);
            stmt = conn.createStatement();
            pslist.add(stmt);

            for (int i = 0; i < sqlList.size(); i++) {
                stmt.executeUpdate(sqlList.get(i));
            }
            conn.commit();

            flag = true;

        }catch (Exception e) {
            e.printStackTrace();
            LOGGER.warn(e.getMessage());
            try {
                conn.rollback();
            } catch (SQLException sqle) {
                LOGGER.warn(sqle.getMessage());
            }
        }finally {
            try {
                if (stmt != null){
                    stmt.close();
                }
                DbConfigUtil.closeConn(conn);
            }catch (Exception e){
                e.printStackTrace();

            }
        }


        return flag;
    }

    /**
     *  复制数据
     * @param sourceData
     * @param destData
     * @param destSourceFeild
     * @throws Exception
     */
    private void copyBizObjectToBizObject(InstanceData sourceData, InstanceData destData,Map<String,String> destSourceFeild) throws Exception {
        String[] strings = destData.getSchema().GetPropertyNames();
        HashMap<String, String> schemaNameValue = new HashMap<>(strings.length);
        for (String s : strings) {
            if (!TableKeyWord.isTableDefaultKeyWord(s)) {
                schemaNameValue.put(s, s);
            }
        }
        if (destSourceFeild != null ) {
            schemaNameValue.putAll(destSourceFeild);
        }
        PropertySchema souceProty ;
        PropertySchema destProty ;
        String destSchemaCode = destData.getSchemaCode();
        String sourceSchemaCode = sourceData.getSchemaCode();
        for (Map.Entry<String,String> entry : schemaNameValue.entrySet()) {
            destProty = destData.getSchema().GetProperty(entry.getKey());
            souceProty = sourceData.getSchema().GetProperty(entry.getValue());
            if (souceProty ==  null || souceProty.getLogicType() == null || destProty == null ||  destProty.getLogicType() == null) {
                continue;
            }
            if (souceProty.getLogicType() != destProty.getLogicType() ){
                LOGGER.warn("数据项类型不一致:"+entry.getKey()+","+souceProty.getLogicType()+";"+entry.getValue()+","+destProty.getLogicType());
                continue;
            }
            if (destProty.getLogicType() == DataLogicType.Comment ){
                continue;
            }
            if (destProty.getLogicType() == DataLogicType.Attachment){
                AppUtility.getEngine().getBizObjectManager().RemoveAttachments(destSchemaCode,destData.getBizObject().getObjectID(),entry.getKey());
                AppUtility.getEngine().getBizObjectManager().CopyAttachments(sourceSchemaCode,sourceData.getBizObject().getObjectID(),entry.getValue(),destSchemaCode,destData.getBizObject().getObjectID(),entry.getKey(),true);
            }else if(isaBizObject(destProty)){
                Object stempVar = sourceData.getItem(entry.getValue()).getValue();
                BizObject[] sourceObjs = (BizObject[])((stempVar instanceof BizObject[]) ? stempVar : null);
                List<BizObject> boList = new ArrayList<BizObject>();
                if (sourceObjs != null) {
                    BizObjectSchema schema = null;
                    schema = destProty.getChildSchema();
                    if (schema == null){
                        continue;
                    }
                    //复制 子表
                    for (BizObject obj : sourceObjs){
                        BizObject tempVar2 = new BizObject(destData.getEngine().getOrganization(), destData.getEngine().getMetadataRepository(), destData.getEngine().getBizObjectManager(), destData.getEngine().getBizBus(), schema, obj.getCreatedBy(), obj.getCreatedByParentId());
                        tempVar2.setObjectID(UUID.randomUUID().toString());
                        tempVar2.setCreatedTime(new java.util.Date());
                        BizObject bo = tempVar2;
                        for (PropertySchema field : obj.getSchema().getProperties())                        {
                            if (TableKeyWord.isChildeDefaultKeyWord(field.getName())){
                                continue;
                            }
                            if (schema.ContainsField(field.getName()))
                            {
                                if (field.getLogicType() == DataLogicType.Attachment){
                                    //将附件从一个数据模型复制到另一个数据模型
                                    AppUtility.getEngine().getBizObjectManager().CopyAttachments(sourceSchemaCode,obj.getObjectID(),souceProty.getChildSchema().getSchemaCode().concat(".").concat(field.getName()),
                                            destSchemaCode,bo.getObjectID(),schema.getSchemaCode().concat(".").concat(field.getName()),true);
                                }else {
                                    bo.setItem(field.getName(), obj.getItem(field.getName()));
                                }
                            }
                        }
                        boList.add(bo);
                    }
                }
                if (!boList.isEmpty()){
                    destData.getBizObject().setItem(entry.getKey(), boList.toArray(new BizObject[]{}));
                }else {
                    destData.getItem(entry.getKey()).setValue(null);

                }
            }else {
                destData.getBizObject().setItem(entry.getKey(),sourceData.getBizObject().GetValue(entry.getValue()));
            }
        }
    }

    /**
     *  判断是否是bizObject
     * @param destProty
     * @return
     */
    private boolean isaBizObject(PropertySchema destProty) {
        return destProty != null && (destProty.getLogicType() == DataLogicType.BizObject   || destProty.getLogicType() == DataLogicType.BizObjectArray);
    }


    /**
     *  执行sql
     * @param ps
     * @param dataContact
     * @param colArray
     * @throws SQLException
     */
    private void executeSql(PreparedStatement ps,List<Map<String, Object>> dataContact,Object[] colArray,JSONObject colMapping) throws SQLException {
        for (int i = 0; i < dataContact.size(); i++) {
            this.psSetParam(ps,dataContact.get(i),colArray,colMapping);
            ps.execute();
        }
    }

    /**
     *  PreparedStatement 赋值
     * @param ps
     * @param param
     * @param colArray
     * @throws SQLException
     */
    private void psSetParam (PreparedStatement ps,Map<String, Object> param ,Object[] colArray,JSONObject colMapping) throws SQLException {
        String[] col ;
        Object val ;
        for (int i = 0; i < colArray.length; i++) {
            col = colMapping.get(colArray[i]).toString().split(",");
            val = param.get(col[0]);
            if("NUMBER".equals(col[1])){
                val = new NUMBER(val==null?0:val);
            }else if("DATE".equals(col[1])){
                if(val == null  || "".equals(val.toString().trim())){
                    val = new Timestamp(System.currentTimeMillis());
                }else if(val instanceof java.util.Date){
                    val = new Timestamp(((java.util.Date) val).getTime());
                }else if(val instanceof TIMESTAMP){
                    val = ((TIMESTAMP) val).getBytes();
                }else if(val instanceof DATE){
                    val = ((DATE) val).getBytes();
                }
               val = new DATE(val);
            }else if("TIMESTAMP".equals(col[1])){
                if(val == null ){
                    val = new TIMESTAMP(new Date(System.currentTimeMillis()));
                }else if(val instanceof TIMESTAMP){
                    val = new TIMESTAMP(((TIMESTAMP) val).getBytes());
                }else if("".equals(val.toString().trim())){
                    val = new TIMESTAMP(new Date(System.currentTimeMillis()));
                }else if(val instanceof DATE){
                    val = new TIMESTAMP(((DATE) val).getBytes());
                }else if(val instanceof java.util.Date){
                    val = new TIMESTAMP( new Date(((java.util.Date) val).getTime()));
                }else if(val instanceof Date){
                    val = new TIMESTAMP((Date)val);
                }
            }else{
                val =   val==null?" ":val.toString();
            }

           /* System.out.println(col[0]+","+col[1]+":"+val);*/
            ps.setObject(i+1, val);
        }

    }



    /**
     * 生成insert sql
     * @param columus
     * @param tableName
     * @return
     */
    private String crateInsertSql(Object[] columus,String tableName){

        StringBuilder sql = new StringBuilder("INSERT INTO "+tableName+"(");

        StringBuilder cols = new StringBuilder();
        StringBuilder vals = new StringBuilder();

        for (int i = 0; i <columus.length ; i++) {
            cols.append("\"").append(columus[i]).append("\",");
            vals.append("? ,");
        }

        cols.deleteCharAt(cols.length()-1);
        vals.deleteCharAt(vals.length()-1);

        sql.append(cols).append(") values (").append(vals).append(")");
        System.out.println(sql.toString());
        return sql.toString();

    }



    /**
     *  关闭连接
     * @param rsList
     * @param stmtList
     * @param conn
     */
    private void closeConnection(List<ResultSet> rsList, List<PreparedStatement> stmtList, Connection conn) {
        try {
            if (CollectionUtils.isNotEmpty(rsList)) {
                for (ResultSet rs :  rsList) {
                    if (null != rs) {
                        rs.close();
                    }
                }
            }

            if (CollectionUtils.isNotEmpty(stmtList)) {
                for (PreparedStatement stmt :  stmtList) {
                    if (null != stmt) {
                        stmt.close();
                    }
                }
            }

            DbConfigUtil.closeConn(conn);

        } catch (SQLException sqle) {
            LOGGER.warn(sqle.getMessage());
        }
    }


    public static void main(String[] args) throws SQLException {
        Object val  = "2019-09-09 10:01:02";
        val = new java.util.Date( System.currentTimeMillis());
        if(val == null  || "".equals(val.toString().trim())){
            val = new Timestamp(System.currentTimeMillis());
        }else if(val instanceof java.util.Date){
            val = new Timestamp(((java.util.Date) val).getTime());
        }else if(val instanceof TIMESTAMP){
            val = ((TIMESTAMP) val).getBytes();
        }else if(val instanceof DATE){
            val = ((DATE) val).getBytes();
        }
        val = new DATE(val);


        System.out.println(val);
    }

}